{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 问题：利用 collections 库的 Counter 方法统计字符串每个单词出现的次数\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "面试官想从这道题中考察面试人什么？\n",
    "在开发过程中，计数这个需求也是会经常碰到的。很多时候，我发现有的开发人员都喜欢自己手写计数函数，或者简单的用一个变量去统计计数。但是一个计数函数可能需要5,6行代码，那你为什么不试试collections.Counter这个方法一行实现呢？而且，它还很快~~\n",
    "\n",
    "答案\n",
    "from collections import Counter\n",
    "\n",
    "print(\" \".join(map(lambda x: x[0] + str(x[1]), Counter(\"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h\").most_common())))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 拓展"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "most_common可以用来产生n个最常遇到的输入值及其各自计数的序列，像下面这个例子。\n",
    "\n",
    "统计一个文本中单词频次最高的10个单词\n",
    "\n",
    "import re\n",
    "from collections import Counter\n",
    "\n",
    "def solution(filepath):\n",
    "    with open(filepath) as f:\n",
    "        return list(map(lambda c: c[0], Counter(re.sub(\"\\W+\", \" \", f.read()).split()).most_common(10)))\n",
    "你可以尝试打印出Counter对象，看看它究竟是一个什么鬼。在底层实现上,一个Counter对象就是一个字典，将元素映射到它出现的次数上。\n",
    "\n",
    ">>> c = Counter(\"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h\")\n",
    ">>> print(c)\n",
    ">>> print(list(c.elements())) # 不保证元素的顺序，不包括计数小于零的项目。\n",
    ">>> for letter, count in c.most_common(3): # 打印频次前三的元素和计数\n",
    "...    print('%s: %7d' % (letter, count))\n",
    "collections 中的常用模块\n",
    "collections模块是一个常用到的模块，这个模块实现了特定目标的容器，以提供Python标准内建容器dict，list，set和 tuple的替代选择。\n",
    "\n",
    "OrderedDict可以实现一个有序的字典，但是在Python3.7之后，内置的dict也可以保留插入的顺序，那么OrderedDict就没有那么重要了。不过它还是有存在的意义的，常规的dict被设计为非常擅长映射操作。OrderedDict旨在擅长重新排序操作。所以，算法上，OrderedDict可以比 dict更好地处理频繁的重新排序操作。\n",
    "\n",
    "defaultdict为字典的不存在的key提供一个默认的值，这样可以减少一些KeyError异常。\n",
    "\n",
    ">>> from collections import OrderedDict, defaultdict,\n",
    ">>> default_dict = defaultdict(str)\n",
    ">>> default_dict['s'] # 一般的字典，如果键s不存在的话，会引发KeyError，而这里我们发现输出是一个默认的空字符\n",
    ">>> print(default_dict) # defaultdict(<class 'str'>, {'s': ''})\n",
    "nametuple是特殊tuple子类，可以用名字和下标来访问元组。它可以构建只有少数属性但是没有方法的对象,比如数据库条目。\n",
    "\n",
    ">>> Person = collections.nametuple('Person', ['name', 'age'])\n",
    ">>> p1 = Person(name='bob', age=17)\n",
    "deque双端队列，可以快速的从另外一侧追加和推出对象。在我们需要从容器的两端更快地执行追加和弹出操作的情况下，与列表相比，首选双端队列，因为与提供O(n)时间复杂度的列表相比，双端队列为追加和弹出操作提供了O(1)时间复杂度。\n",
    "\n",
    ">>> de = collections.deque([1,2,3])\n",
    ">>> de.append(4) # deque([1, 2, 3, 4])\n",
    ">>> de.pop() # 4\n",
    ">>> de.popleft() # 1"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}